package math;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import math.common.MathCommon;

public class AdjEntropy implements Entropy {
	
	public AdjEntropy () {
		
	}
	
	//Optimal number of intervals
	private Integer getIntervalsNum(List<Double> sample) {
		Double D = MathCommon.quantile(sample, 0.9) - MathCommon.quantile(sample, 0.1);
		Double As = MathCommon.skewness(sample);
		int N = sample.size();
		Double intervalsNum = 1.072*Math.pow(N, 0.968-0.231D)-2.098*As-1.789;
		return intervalsNum.intValue();
	}
	
	public Double getSmplEntropy (List<Double> sample) {
		int M = getIntervalsNum(sample);
		List<Double> sortedSample = new ArrayList<Double> ();
		sortedSample.addAll(sample);
		Collections.sort(sortedSample);
		Double min = Collections.min(sample);
		Double h = (Collections.max(sample)-min)/M;
		Double E = 0.0;
		//List<Double> p = new ArrayList<Double> ();
		int i = 1;
		int j=0;
		Double p = 0.0;
		for (Double val : sortedSample) {
			if ((val < min+i*h)&&(val >= min+(i-1)*h)) {
				p += 1.0/h;
				j++;
			} else {
				if (j>0) {
					E += -p/j*Math.log10(p/j);
					p = 0.0;
					j = 0;
				}
				i++;
			}
 				
				
		}
	
		return E;
	}

	

}
